%%%-------------------------------------------------------------------
%%% @author Administrator
%%% @copyright (C) 2019, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 15. 10月 2019 17:38
%%%-------------------------------------------------------------------
-module(database).
-author("Administrator").

-include("include/logger.hrl").
-include("include/game.hrl").

-behaviour(gen_server).

%% API
-export([start_link/0, select_player_info/0,
  update_player_info/1, select_task/0,
  select_player_info/1,
  select_task/1, update_player_state/1, update_login_state/1,
  update_logout_state/1, rand_player/1, init_app/0, update_task_status/2,players/0]).

%% gen_server callbacks
-export([init/1,
  handle_call/3,
  handle_cast/2,
  handle_info/2,
  terminate/2,
  code_change/3]).

-define(SERVER, ?MODULE).

-record(state, {mysqlPid}).

%%%===================================================================
%%% API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Starts the server
%%
%% @end
%%--------------------------------------------------------------------
-spec(start_link() ->
  {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
start_link() ->
  gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Initializes the server
%%
%% @spec init(Args) -> {ok, State} |
%%                     {ok, State, Timeout} |
%%                     ignore |
%%                     {stop, Reason}
%% @end
%%--------------------------------------------------------------------
-spec(init(Args :: term()) ->
  {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term()} | ignore).
init([]) ->
  Host = myshare:get_env(db_ls_host),
  User = myshare:get_env(db_ls_user),
  PassWd = myshare:get_env(db_ls_pass),
  DbName = myshare:get_env(db_ls_name),
  {ok, Pid} = mysql:start_link([{host, Host}, {user, User},
    {password, PassWd}, {database, DbName}]),
  erlang:register(mysqlPid, Pid),
  {ok, #state{mysqlPid = Pid}}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling call messages
%%
%% @end
%%--------------------------------------------------------------------
-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
    State :: #state{}) ->
  {reply, Reply :: term(), NewState :: #state{}} |
  {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
  {noreply, NewState :: #state{}} |
  {noreply, NewState :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
  {stop, Reason :: term(), NewState :: #state{}}).
handle_call(_Request, _From, State) ->
  {reply, ok, State}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling cast messages
%%
%% @end
%%--------------------------------------------------------------------
-spec(handle_cast(Request :: term(), State :: #state{}) ->
  {noreply, NewState :: #state{}} |
  {noreply, NewState :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term(), NewState :: #state{}}).
handle_cast(_Request, State) ->
  {noreply, State}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling all non call/cast messages
%%
%% @spec handle_info(Info, State) -> {noreply, State} |
%%                                   {noreply, State, Timeout} |
%%                                   {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
  {noreply, NewState :: #state{}} |
  {noreply, NewState :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term(), NewState :: #state{}}).
handle_info(_Info, State) ->
  {noreply, State}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any
%% necessary cleaning up. When it returns, the gen_server terminates
%% with Reason. The return value is ignored.
%%
%% @spec terminate(Reason, State) -> void()
%% @end
%%--------------------------------------------------------------------
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
    State :: #state{}) -> term()).
terminate(_Reason, _State) ->
  ok.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Convert process state when code is changed
%%
%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
%% @end
%%--------------------------------------------------------------------
-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
    Extra :: term()) ->
  {ok, NewState :: #state{}} | {error, Reason :: term()}).
code_change(_OldVsn, State, _Extra) ->
  {ok, State}.

%%%===================================================================
%%% Internal functions
%%%===================================================================

%%查询所有玩家信息
select_player_info() ->
  {ok, _ColumnNames, Rows} =
    mysql:query(mysqlPid, <<"SELECT account,password,is_new_player FROM player_infos where id =39 ">>),
  player_assist:assemblePlayerData(Rows).

select_player_info(Account) ->
  ?DEBUG("select_player_info,Account:~p", [Account]),
  {ok, _ColumnNames, Rows} =
    mysql:query(mysqlPid, <<"SELECT account,password,is_new_player FROM player_infos where account=?">>, [Account]),
  case Rows of
    [] -> [];
    _ -> player_assist:assemblePlayerData(Rows)
  end.

%%更新玩家数据
update_player_info(Params) ->
  ?INFO("update_player_info params:~p", [Params]),
  ok = mysql:query(mysqlPid,
    <<"UPDATE player_infos SET is_new_player=0,nickName=?,playerId=?,fullHeadImg=? where account=?">>,
    Params).
%%更新玩家游戏状态
update_player_state(Params) ->
  ?DEBUG("update_player_state params:~p", [Params]),
  ok = mysql:query(mysqlPid,
    <<"UPDATE player_infos SET game_id=?,room_id=? where account=?">>,
    Params).

%%玩家登录状态
update_login_state(Params) ->
  ?DEBUG("update_login_state params:~p", [Params]),
  ok = mysql:query(mysqlPid,
    <<"UPDATE player_infos SET is_online=1,task_id=? where account=?">>,
    Params).
%%玩家退出状态
update_logout_state(Account) ->
  Params = [Account],
  ?DEBUG("update_logout_state params:~p", [Params]),
  ok = mysql:query(mysqlPid,
    <<"UPDATE player_infos SET is_online=0,game_id=0,room_id=0 where account=?">>,
    Params).

%%查询任务
select_task() ->
  {ok, _ColumnNames, Rows} =
    mysql:query(mysqlPid, <<"SELECT a.`id`,a.`name`,a.`game_ids`,a.player_number,a.`condition`,a.`take_number`,
    a.`all_day_run`,a.`look_number`,b.`start_time`,b.`end_time`,c.`start_number`,c.`end_number` FROM tasks a INNER JOIN time_configs b
    ON a.time_id = b.id INNER JOIN take_configs c ON a.take_id=c.id where a.is_complete=0">>),
  Rows.

rand_player(Number) ->
  {ok, _ColumnNames, Rows} =
    mysql:query(mysqlPid, <<"SELECT `account`,`password`,`is_new_player` FROM player_infos WHERE is_online = 0 ORDER BY RAND() LIMIT ? ">>
      , [Number]),
  Rows.

select_task(TaskId) ->
  ?DEBUG("select_task id:~p", [TaskId]),
  {ok, _ColumnNames, Rows} =
    mysql:query(mysqlPid, <<"SELECT a.`id`,a.`name`,a.`game_ids`,a.player_number,a.`condition`,a.`take_number`,a.`all_day_run`,
    a.`look_number`,b.`start_time`,
	  b.`end_time`,c.`start_number`,c.`end_number` FROM tasks a INNER JOIN time_configs b ON a.time_id = b.id
	  INNER JOIN take_configs c ON a.take_id=c.id where a.id=?">>, [TaskId]),
  Rows.

%%启动应用重置玩家状态
init_app() ->
  ok = mysql:query(mysqlPid,
    <<"UPDATE player_infos SET is_online=0,game_id=0,room_id=0;
    UPDATE tasks set is_complete=0;">>).

%%更新所有任务状态
update_task_status(Task_id, Status) ->
  ok = mysql:query(mysqlPid,
    <<"UPDATE tasks set is_complete=? where id=?">>, [Status,Task_id]).

%%取所有账号数据
players()->
  {ok, _ColumnNames, Rows} =
  mysql:query(mysqlPid,<<"select account,password,is_new_player from player_infos">>),
  Rows.


